﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.DirectoryServices;
using System.IO;
using System.Text.RegularExpressions;

namespace WebApp.Code
{
    public class ADEntry
    {
        private const string USER_PROPERTY_NAME = "displayName";
        private const string USER_PROPERTY_USERNAME = "sAMAccountName";
        private const string distinguishedName = "distinguishedName";
        private const string gPLink = "gPLink";
        private const string gPCFileSysPath = "gPCFileSysPath";
        private const string LDAPHead = "LDAP://ceibs.edu";
        private const string LDAPRoot = "LDAP://ceibs.edu/CN=Users,DC=ceibs,DC=edu";

        Profile userProfile = new Profile();
        public Profile UserProfile
        {
            get { return userProfile; }
        }

        protected string UserName
        {
            get;
            set;
        }

        protected string Password
        {
            get;
            set;
        }

        public ADEntry(string userName, string password)
        {
            UserName = userName;
            Password = password;

            GetUserHomeDrive();
            GetUserGroupPolicyDrive();
        }
        protected void GetUserHomeDrive()
        {
            if (String.IsNullOrEmpty(UserName))
                return;

            using (DirectoryEntry root = new DirectoryEntry(LDAPHead))
            {
                root.Username = UserName;
                root.Password = Password;

                using (DirectorySearcher ds = new DirectorySearcher(root))
                {
                    ds.Filter = String.Format(
                        "(&(objectCategory=person)(objectClass=user)(sAMAccountName={0}))", UserName);

                    try
                    {
                        SearchResult sr = ds.FindOne();
                        if (sr == null)
                            return;
                        ResultPropertyValueCollection driveValue = sr.Properties["homeDrive"];
                        ResultPropertyValueCollection directoryValue = sr.Properties["homeDirectory"];
                        if (driveValue.Count > 0 && directoryValue.Count > 0)
                        {
                            userProfile.NetDrives.Add(new NetDrive(driveValue[0].ToString().Replace(":", ""), directoryValue[0].ToString()));
                        }
                        return;
                    }
                    catch (DirectoryServicesCOMException)
                    {
                        
                    }
                }
            }
        }

        protected void GetUserGroupPolicyDrive()
        {
            string batFile = GetBatFile();
            if (string.IsNullOrEmpty(batFile))
                return;

            using (StreamReader sr = new StreamReader(batFile))
            {
                string text = sr.ReadToEnd();

                AppendUserDrive(text, @"^net use (\w):\s?(\\\\.*)$");
                AppendUserDrive(text, @"^WshNetwork.MapNetworkDrive\s?(.+),(.+)$");
            }
        }
        protected void AppendUserDrive(string text, string reg)
        {
            Regex regex = new Regex(reg, RegexOptions.IgnoreCase | RegexOptions.Multiline);
            MatchCollection matchCollection = regex.Matches(text);
            foreach (Match match in matchCollection)
            {
                if (match.Groups[1].Success && match.Groups[2].Success)
                {
                    string driveName = match.Groups[1].Value.Replace("\"", string.Empty).Replace(":", string.Empty).Trim();
                    string drivePath = match.Groups[2].Value.Replace("\"", string.Empty).Trim();
                    userProfile.NetDrives.Add(new NetDrive(driveName, drivePath));
                }
            }
        }
        private string GetBatFile()
        {
            string path = GetPcPath();
            if (string.IsNullOrEmpty(path))
                return string.Empty;
            try
            {
                using (StreamReader scriptSR = new StreamReader(string.Format("{0}\\User\\Scripts\\scripts.ini", path)))
                {
                    string scriptText = scriptSR.ReadToEnd();
                    Regex regex = new Regex(@"0CmdLine=(\w+.(bat|VBS))", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Multiline);
                    MatchCollection mc = regex.Matches(scriptText);
                    if (mc.Count > 0 && mc[0].Groups[1].Success)
                    {
                        string batName = mc[0].Groups[1].Value;
                        return string.Format("{0}\\User\\Scripts\\Logon\\{1}", path, batName);
                    }
                    return string.Empty;
                }
            }
            catch
            {
                return string.Empty;
            }
        }
        private string GetPcPath()
        {
            string distinguished = GetUserDistinguishedNameByAD();
            if (string.IsNullOrEmpty(distinguished))
                return string.Empty;

            int m = distinguished.IndexOf(",") + 1;
            string gplinkPath = string.Format("{0}/{1}", LDAPHead, distinguished.Substring(m));
            string gplink = GetDirctoryPathProperty(gplinkPath, gPLink);
            if (string.IsNullOrEmpty(gplink))
                return string.Empty;

            gplink = gplink.Replace("[LDAP://", "");
            int nIndex = gplink.LastIndexOf(";");
            string gpcFileSysPath = string.Format("{0}/{1}", LDAPHead, gplink.Substring(0, nIndex));
            string pcPath = GetDirctoryPathProperty(gpcFileSysPath, gPCFileSysPath);
            if (string.IsNullOrEmpty(pcPath))
                return string.Empty;

            return pcPath;
        }

        private string GetUserDistinguishedNameByAD()
        {
            using (DirectoryEntry root = new DirectoryEntry(LDAPHead))
            {
                root.Username = UserName;
                root.Password = Password;
                using (DirectorySearcher ds = new DirectorySearcher(root))
                {
                    ds.Filter = String.Format(
                        "(&(objectCategory=person)(objectClass=user)({0}={1}))",
                         USER_PROPERTY_USERNAME,
                         UserName);

                    try
                    {
                        SearchResult sr = ds.FindOne();
                        if (sr == null)
                            return string.Empty;
                        object propertyValue = null;
                        if (sr.Properties.Contains(distinguishedName) && sr.Properties[distinguishedName].Count > 0)
                        {
                            propertyValue = sr.Properties[distinguishedName][0];
                        }

                        if (propertyValue != null)
                            return propertyValue.ToString();
                        else
                            return string.Empty;
                    }
                    catch (DirectoryServicesCOMException)
                    {
                        return string.Empty;
                    }
                }
            }
        }
        private string GetDirctoryPathProperty(string path, string propertyName)
        {
            using (DirectoryEntry root = new DirectoryEntry(path, UserName, Password))
            {
                object propertyValue = null;
                if (root.Properties.Contains(propertyName))
                    propertyValue = root.Properties[propertyName].Value;

                if (propertyValue != null)
                    return propertyValue.ToString();
                else
                    return string.Empty;
            }
        }
    }
}